﻿using System.Collections.Concurrent;
using SweeperPrototype.Business;
using SweeperPrototype.Business.Fields;
using SweeperPrototype.Business.Keys;

namespace SweeperPrototype.Objects
{
    public partial class EffectiveExposure
    {
        private const int MAX_UPDATE_LOOKBACK = 50;

        private readonly ConcurrentQueue<EffectiveExposureUpdate> m_UpdateStack;
        private EffectiveExposureUpdate m_LastUpdate;
        private readonly PositionSubscription m_PositionSubscription;
        private readonly ExposureMappingSubscription m_ExposureSubscription;

        public EffectiveExposure( PositionSubscription subscription, ExposureMappingSubscription exposure )
        {
            m_UpdateStack = new ConcurrentQueue<EffectiveExposureUpdate>();
            m_PositionSubscription = subscription;
            m_ExposureSubscription = exposure;

            m_ExposureSubscription = exposure;

            if (exposure.IsValid || subscription.IsValid)
            {
                EffectiveExposureUpdate update = new EffectiveExposureUpdate(this, exposure.LastUpdate, subscription.LastUpdate);
                Update( update );
            }

            m_PositionSubscription.Updated += delegate(PositionSubscription source, PositionSubscription.PositionUpdate update, PositionSubscription.PositionUpdate old_update)
            {
                Update(new EffectiveExposureUpdate(this, update));
            };
            m_ExposureSubscription.Updated += delegate(ExposureMappingSubscription source, ExposureMappingSubscription.ExposureMappingUpdate update, ExposureMappingSubscription.ExposureMappingUpdate old_update)
            {
                Update(new EffectiveExposureUpdate(this, update));
            };
        }

        // ---------- READONLY IDENTITIES
        public BookCode BookCode
        {
            get { return m_PositionSubscription.BookCode; }
        }

        public ExposureRIC RIC
        {
            get { return m_PositionSubscription.RIC; }
        }

        public ExposureRIC ExposureRIC
        {
            get { return m_ExposureSubscription.ExposureRIC; }
        }

        public EffectiveRIC EffectiveRIC
        {
            get { return m_ExposureSubscription.EffectiveRIC; }
        }
        // ----------- DYNAMIC STATE


        public Shares Quantity
        {
            get{ return m_LastUpdate == null ? null : m_LastUpdate.Quantity; }
        }


        public Multiplier Multiplier
        {
            get { return m_LastUpdate == null ? null : m_LastUpdate.Multiplier; }
        }

        public Timestamp Timestamp{
            get { return m_LastUpdate == null ? null : m_LastUpdate.Timestamp; }
        }


        public bool IsValid
        {
            get
            {
                return m_PositionSubscription.IsValid
                   && m_ExposureSubscription.IsValid;
            }
        }

        public void Update( EffectiveExposureUpdate update )
        {
            EffectiveExposureUpdate previous = m_LastUpdate;
            m_LastUpdate = update;
            m_UpdateStack.Enqueue(previous);

            Updated(this, previous, update);

            if (m_UpdateStack.Count > MAX_UPDATE_LOOKBACK)
            {
                EffectiveExposureUpdate dequeued;
                while (m_UpdateStack.TryDequeue(out dequeued) == false) { }
            }
        }

        public event UpdateDelegate<EffectiveExposure, EffectiveExposureUpdate> Updated = delegate { };


    }
}